/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#ifndef MC_BUILTINS_LIST_H
#define MC_BUILTINS_LIST_H

#include "mcpy/builtins/cast.h"
#include "mcpy/exception.h"
#include <algorithm>
#include <cstdint>
#include <functional>
#include <map>
#include <set>
#include <string>
#include <type_traits>

#include <mc/array.h>
#include <mc/format.h>
#include <mc/variant.h>

namespace mcpy {

// ============================================================================
// mc::variants 辅助函数
// 为弱类型数组 mc::variants 提供与 list[T] 一致的接口
// ============================================================================

MC_API mc::variant_reference list_getitem(mc::variants& container, int index);
MC_API mc::variant list_getitem(const mc::variants& container, int index);
MC_API void        list_setitem(mc::variants& container, int index, const mc::variant& value);
MC_API mc::variant list_pop_back(mc::variants& container);
MC_API mc::variant list_pop(mc::variants& container, size_t index);
MC_API void        list_remove(mc::variants& container, const mc::variant& item);

// ============================================================================
// mc::array<T> 辅助函数
// ============================================================================

/**
 * @brief 从可迭代容器构造 list（模板化，和 dict_pop/set_construct 一样）
 *
 * @tparam ElementType Python 侧的元素类型（从 list[T] 推导）
 * @param container 可迭代容器
 * @return mc::array<ElementType> 强类型数组
 *
 * 用法：
 *   Python: lst: list[int] = list(s)  其中 s: set[int]
 *   C++:    mc::array<int> lst = mcpy::list_construct<int>(s);
 *
 * 设计理念（和 dict_pop/set_construct 完全一致）：
 * - **必须明确指定目标元素类型**（不能从容器自动推导）
 * - 类型转换在函数内部完成：
 *   1. 如果源容器元素类型和目标类型一致，直接复制（优化）
 *   2. 如果源是 mc::variant，使用 cast<T>() 转换
 *   3. 如果源可以转换为目标类型，使用 static_cast 转换
 *   4. 否则先转 variant 再转目标类型
 */
template <typename ElementType, typename Container>
auto list_construct(const Container& container)
    -> mc::array<ElementType> {
    mc::array<ElementType> result;
    result.reserve(container.size());
    using SourceType = typename Container::value_type;
    for (const auto& item : container) {
        if constexpr (std::is_same_v<ElementType, SourceType>) {
            // 类型相同，直接复制
            result.push_back(item);
        } else if constexpr (std::is_same_v<SourceType, mc::variant>) {
            // 源是 variant，使用 cast
            result.push_back(mcpy::cast<ElementType>(item));
        } else if constexpr (std::is_convertible_v<SourceType, ElementType>) {
            // 源可以直接转换为目标类型（如 int -> float）
            result.push_back(static_cast<ElementType>(item));
        } else {
            // 需要先转换为 variant，再转换
            result.push_back(mcpy::cast<ElementType>(mc::variant(item)));
        }
    }
    return result;
}

// 嵌套列表推导式辅助函数
// 使用类型推导让返回类型与赋值目标匹配
// 用法: auto flat = list_comp_nested<ElementType>([&]() { /* 推导式逻辑 */ });
template <typename ElementType, typename Func>
mc::array<ElementType> list_comp_nested(Func&& func) {
    auto                   temp_result = func(); // 执行 lambda，得到 mc::variants
    mc::array<ElementType> result;
    result.reserve(temp_result.size());
    for (const auto& item : temp_result) {
        result.push_back(item.template as<ElementType>());
    }
    return result;
}

// 列表推导式辅助函数（自动推导返回类型）
// 用法: auto result = list_comprehension(container, [](const auto& x) { return transform(x); });
template <typename Container, typename Func>
auto list_comprehension(const Container& container, Func&& func)
    -> mc::array<decltype(func(*container.begin()))> {
    using ResultType = decltype(func(*container.begin()));
    mc::array<ResultType> result;
    result.reserve(container.size()); // 假设 container 支持 size()
    for (const auto& item : container) {
        result.push_back(func(item));
    }
    return result;
}

// 列表推导式辅助函数（显式指定元素类型，支持类型转换）
// 用法: auto result = list_comprehension<int>(container, [](const auto& x) { return x; });
// 当容器元素是 mc::variant 或 variant_reference 时，会自动进行类型转换
template <typename ElementType, typename Container, typename Func>
mc::array<ElementType> list_comprehension(const Container& container, Func&& func) {
    mc::array<ElementType> result;
    result.reserve(container.size());
    for (const auto& item : container) {
        // 对于 mc::variant/variant_reference，使用 .as<ElementType>() 进行类型转换
        // 对于其他类型，直接转换
        auto transformed      = func(item);
        using TransformedType = decltype(transformed);
        if constexpr (std::is_same_v<TransformedType, mc::variant> ||
                      std::is_same_v<TransformedType, const mc::variant&> ||
                      std::is_same_v<TransformedType, mc::variant&> ||
                      std::is_same_v<TransformedType, mc::variant_reference> ||
                      std::is_same_v<TransformedType, const mc::variant_reference&>) {
            // variant 和 variant_reference 都支持 as<T>() 方法
            result.push_back(transformed.template as<ElementType>());
        } else {
            result.push_back(static_cast<ElementType>(transformed));
        }
    }
    return result;
}

// 带条件筛选的列表推导式（自动推导返回类型）
// 用法: auto result = list_comprehension_if(container,
//                                           [](const auto& x) { return transform(x); },
//                                           [](const auto& x) { return condition(x); });
template <typename Container, typename TransformFunc, typename FilterFunc>
auto list_comprehension_if(const Container& container,
                           TransformFunc&&  transform,
                           FilterFunc&&     filter)
    -> mc::array<decltype(transform(*container.begin()))> {
    using ResultType = decltype(transform(*container.begin()));
    mc::array<ResultType> result;
    for (const auto& item : container) {
        if (filter(item)) {
            result.push_back(transform(item));
        }
    }
    return result;
}

// 带条件筛选的列表推导式（显式指定元素类型，支持类型转换）
// 用法: auto result = list_comprehension_if<int>(container,
//                                                [](const auto& x) { return x; },
//                                                [](const auto& x) { return x > 0; });
template <typename ElementType, typename Container, typename TransformFunc, typename FilterFunc>
mc::array<ElementType> list_comprehension_if(const Container& container,
                                             TransformFunc&&  transform,
                                             FilterFunc&&     filter) {
    mc::array<ElementType> result;
    for (const auto& item : container) {
        if (filter(item)) {
            auto transformed      = transform(item);
            using TransformedType = decltype(transformed);
            if constexpr (std::is_same_v<TransformedType, mc::variant> ||
                          std::is_same_v<TransformedType, const mc::variant&> ||
                          std::is_same_v<TransformedType, mc::variant&> ||
                          std::is_same_v<TransformedType, mc::variant_reference> ||
                          std::is_same_v<TransformedType, const mc::variant_reference&>) {
                // variant 和 variant_reference 都支持 as<T>() 方法
                result.push_back(transformed.template as<ElementType>());
            } else {
                result.push_back(static_cast<ElementType>(transformed));
            }
        }
    }
    return result;
}

// list_index函数实现
template <typename Container, typename U>
size_t list_index(const Container& container, const U& item) {
    auto it = std::find(container.begin(), container.end(), item);
    if (it == container.end()) {
        MC_THROW(mcpy::value_error, "item is not in list");
    }
    return std::distance(container.begin(), it);
}

// list_index函数实现（支持start和end参数）
template <typename Container, typename U>
size_t list_index(const Container& container, const U& item, int start, int end) {
    int size = static_cast<int>(container.size());

    // 处理负索引
    if (start < 0) {
        start += size;
    }
    if (end < 0) {
        end += size;
    }

    // 边界检查和调整
    start = std::max(0, std::min(start, size));
    end   = std::max(0, std::min(end, size));

    // 如果start >= end，则搜索范围为空
    if (start >= end) {
        MC_THROW(mcpy::value_error, "item is not in list");
    }

    auto search_start = container.begin() + start;
    auto search_end   = container.begin() + end;
    auto it           = std::find(search_start, search_end, item);

    if (it == search_end) {
        MC_THROW(mcpy::value_error, "item is not in list");
    }

    return std::distance(container.begin(), it);
}

// list_pop函数实现
template <typename T>
T list_pop(mc::array<T>& container, size_t index) {
    if (index >= container.size()) {
        MC_THROW(mcpy::index_error, "pop index out of range");
    }
    auto value = container[index];
    container.erase(container.begin() + index);
    return value;
}

// list_remove函数实现
template <typename T, typename U>
void list_remove(mc::array<T>& container, U&& item) {
    auto it = std::find(container.begin(), container.end(), std::forward<U>(item));
    if (it == container.end()) {
        MC_THROW(mcpy::value_error, "list.remove(x): x not in list");
    }
    container.erase(it);
}

// list_pop_back函数实现
template <typename T>
T list_pop_back(mc::array<T>& container) {
    if (container.empty()) {
        MC_THROW(mcpy::index_error, "pop from empty list");
    }
    T value = container.back();
    container.pop_back();
    return value;
}

// ============================================================================
// list_concat 重载函数族
// ============================================================================
template <typename T>
mc::array<T> list_concat(const mc::array<T>& lhs, const mc::array<T>& rhs) {
    mc::array<T> result;
    result.reserve(lhs.size() + rhs.size());
    result.insert(result.end(), lhs.begin(), lhs.end());
    result.insert(result.end(), rhs.begin(), rhs.end());
    return result;
}

template <typename T, typename U,
          std::enable_if_t<std::is_same_v<std::decay_t<U>, mc::variants>, int> = 0>
mc::array<T> list_concat(const mc::array<T>& lhs, U&& rhs) {
    mc::array<T> result;
    result.reserve(lhs.size() + rhs.size());
    result.insert(result.end(), lhs.begin(), lhs.end());
    for (const auto& item : rhs) {
        result.push_back(cast<T>(item));
    }
    return result;
}

template <typename T, typename U,
          std::enable_if_t<mc::is_variant_v<U>, int> = 0>
mc::array<T> list_concat(const mc::array<T>& lhs, U&& rhs) {
    return list_concat(lhs, rhs.get_array());
}

template <typename T>
mc::variants list_concat(const mc::variants& lhs, const mc::array<T>& rhs) {
    mc::variants result;
    result.reserve(lhs.size() + rhs.size());
    result.insert(result.end(), lhs.begin(), lhs.end());
    for (const auto& item : rhs) {
        result.push_back(item);
    }
    return result;
}

template <typename U,
          std::enable_if_t<std::is_same_v<std::decay_t<U>, mc::variants>, int> = 0>
mc::variants list_concat(const mc::variants& lhs, U&& rhs) {
    mc::variants result;
    result.reserve(lhs.size() + rhs.size());
    result.insert(result.end(), lhs.begin(), lhs.end());
    result.insert(result.end(), rhs.begin(), rhs.end());
    return result;
}

template <typename U,
          std::enable_if_t<mc::is_variant_v<U>, int> = 0>
mc::variants list_concat(const mc::variants& lhs, U&& rhs) {
    return list_concat(lhs, rhs.get_array());
}

// list += 操作符实现
template <typename T>
mc::array<T>& list_iadd(mc::array<T>& lhs, const mc::array<T>& rhs) {
    lhs.insert(lhs.end(), rhs.begin(), rhs.end());
    return lhs;
}

template <typename T, typename U,
          std::enable_if_t<std::is_same_v<std::decay_t<U>, mc::variants>, int> = 0>
mc::array<T>& list_iadd(mc::array<T>& lhs, U&& rhs) {
    lhs.reserve(lhs.size() + rhs.size());
    for (const auto& item : rhs) {
        lhs.push_back(cast<T>(item));
    }
    return lhs;
}

template <typename T, typename U,
          std::enable_if_t<mc::is_variant_v<U>, int> = 0>
mc::array<T>& list_iadd(mc::array<T>& lhs, U&& rhs) {
    return list_iadd(lhs, rhs.get_array());
}

template <typename T>
mc::variants& list_iadd(mc::variants& lhs, const mc::array<T>& rhs) {
    lhs.reserve(lhs.size() + rhs.size());
    for (const auto& item : rhs) {
        lhs.push_back(item);
    }
    return lhs;
}

template <typename U,
          std::enable_if_t<std::is_same_v<std::decay_t<U>, mc::variants>, int> = 0>
mc::variants& list_iadd(mc::variants& lhs, U&& rhs) {
    lhs.reserve(lhs.size() + rhs.size());
    lhs.insert(lhs.end(), rhs.begin(), rhs.end());
    return lhs;
}

template <typename U,
          std::enable_if_t<mc::is_variant_v<U>, int> = 0>
mc::variants& list_iadd(mc::variants& lhs, U&& rhs) {
    return list_iadd(lhs, rhs.get_array());
}

// list extend 方法
template <typename Container1, typename Container2>
void list_extend(Container1& lhs, const Container2& rhs) {
    list_iadd(lhs, rhs);
}

template <typename Container, typename T>
void list_extend(Container& lhs, std::initializer_list<T> rhs) {
    for (const auto& item : rhs) {
        lhs.push_back(item);
    }
}

// list 成员检测
template <typename Container, typename U>
bool list_contains(const Container& container, const U& item) {
    return std::find(container.begin(), container.end(), item) != container.end();
}

// list 插入元素
template <typename Container, typename U>
void list_insert(Container& container, int index, const U& item) {
    container.insert(container.begin() + index, item);
}

// list 计数元素
template <typename Container, typename U>
size_t list_count(const Container& container, const U& item) {
    return std::count(container.begin(), container.end(), item);
}

// list 反转
template <typename Container>
void list_reverse(Container& container) {
    std::reverse(container.begin(), container.end());
}

// ============================================================================
// 列表索引和元素访问
// ============================================================================

// list索引访问
// 对于 bool 类型，返回 bool 值（因为 std::vector<bool> 返回代理对象）
// 对于其他类型，返回 T& 引用
template <typename T>
std::conditional_t<std::is_same_v<T, bool>, bool, T&> list_getitem(
    mc::array<T>& container, int index) {
    int size = static_cast<int>(container.size());

    // 处理负索引
    if (index < 0) {
        index += size;
    }

    // 边界检查
    if (index < 0 || index >= size) {
        MC_THROW(mcpy::index_error, "list index out of range");
    }

    return container[index];
}

// list索引访问（const版本）
template <typename T>
std::conditional_t<std::is_same_v<T, bool>, bool, const T&> list_getitem(
    const mc::array<T>& container, int index) {
    return list_getitem(const_cast<mc::array<T>&>(container), index);
}

// list索引赋值（支持负索引）
template <typename T>
void list_setitem(mc::array<T>& container, int index, const T& value) {
    int size = static_cast<int>(container.size());

    // 处理负索引
    if (index < 0) {
        index += size;
    }

    // 边界检查
    if (index < 0 || index >= size) {
        MC_THROW(mcpy::index_error, "list assignment index out of range");
    }

    container[index] = value;
}

// list删除元素（支持负索引）
template <typename Container>
void list_delitem(Container& container, int index) {
    int size = static_cast<int>(container.size());

    // 处理负索引
    if (index < 0) {
        index += size;
    }

    // 边界检查
    if (index < 0 || index >= size) {
        MC_THROW(mcpy::index_error, "list assignment index out of range");
    }

    container.erase(container.begin() + index);
}

// list *= 操作符实现
template <typename Container>
Container& list_imul(Container& container, int n) {
    if (n <= 0) {
        container.clear();
        return container;
    }

    if (n == 1) {
        return container;
    }

    std::size_t old_size = container.size();
    container.reserve(old_size * n);

    auto end_pos = container.begin() + old_size;
    for (int i = 1; i < n; ++i) {
        container.insert(container.end(), container.begin(), end_pos);
    }

    return container;
}

// list重复（乘法操作）
template <typename Container>
Container list_repeat(const Container& container, int n) {
    if (n <= 0) {
        return {};
    }

    Container result = container.copy();
    list_imul(result, n);
    return result;
}

// list转字符串表示（__repr__和__str__）
template <typename Container>
std::string list_repr(const Container& container) {
    std::string                  result;
    mc::fmt::format_context      context(result);
    mc::fmt::detail::format_spec spec;
    return mc::fmt::detail::format_to(context, spec, container);
}

// list排序
template <typename Container>
void list_sort(Container& container, bool reverse = false) {
    if (reverse) {
        using T = typename Container::value_type;
        std::sort(container.begin(), container.end(), std::greater<T>());
    } else {
        std::sort(container.begin(), container.end());
    }
}

// 切片辅助函数：规范化切片索引
MC_API void normalize_slice_indices(
    int64_t  size,
    int64_t* start,
    int64_t* stop,
    int64_t  step);

// 切片读取：list[start:stop:step]
template <typename Container>
Container list_slice(
    const Container& container,
    int64_t          start = INT64_MIN,
    int64_t          stop  = INT64_MIN,
    int64_t          step  = 1) {
    int64_t size = static_cast<int64_t>(container.size());

    // 规范化索引
    normalize_slice_indices(size, &start, &stop, step);

    Container result;
    if (step > 0) {
        for (int64_t i = start; i < stop; i += step) {
            result.push_back(container[i]);
        }
    } else {
        for (int64_t i = start; i > stop; i += step) {
            result.push_back(container[i]);
        }
    }

    return result;
}

// 切片赋值：list[start:stop:step] = values
template <typename Container1, typename Container2>
void list_slice_assign(
    Container1&       container,
    const Container2& values,
    int64_t           start = INT64_MIN,
    int64_t           stop  = INT64_MIN,
    int64_t           step  = 1) {
    int64_t size = static_cast<int64_t>(container.size());

    // 规范化索引
    normalize_slice_indices(size, &start, &stop, step);

    if (step == 1) {
        // step == 1: 可以改变列表长度
        int64_t old_slice_len = (start < stop) ? (stop - start) : 0;
        int64_t new_slice_len = static_cast<int64_t>(values.size());
        int64_t delta         = new_slice_len - old_slice_len;

        if (delta != 0) {
            int64_t old_size = static_cast<int64_t>(container.size());
            int64_t new_size = old_size + delta;
            if (delta > 0) {
                // 扩大：先调整大小，再从后往前移动，避免覆盖
                container.resize(static_cast<size_t>(new_size));
                for (int64_t i = old_size - 1; i >= stop; --i) {
                    container[i + delta] = std::move(container[i]);
                }
            } else {
                // 缩小：先从前往后移动，再调整大小
                for (int64_t i = stop; i < old_size; ++i) {
                    container[i + delta] = std::move(container[i]);
                }
                container.resize(static_cast<size_t>(new_size));
            }
        }

        // 复制新值到目标位置
        for (size_t i = 0; i < values.size(); ++i) {
            container[start + i] = values[i];
        }
    } else {
        // step != 1: 必须长度匹配（扩展切片赋值）
        int64_t slice_len = 0;
        if (step > 0) {
            slice_len = (start < stop) ? ((stop - start + step - 1) / step) : 0;
        } else {
            slice_len = (start > stop) ? ((start - stop - step - 1) / (-step)) : 0;
        }

        if (slice_len != static_cast<int64_t>(values.size())) {
            MC_THROW(
                mcpy::value_error,
                "扩展切片赋值时长度必须匹配: 切片长度=${slice_len}, 值长度=${value_len}",
                ("slice_len", std::to_string(slice_len))("value_len", std::to_string(values.size())));
        }

        // 逐个赋值
        size_t value_idx = 0;
        if (step > 0) {
            for (int64_t i = start; i < stop; i += step) {
                container[i] = values[value_idx++];
            }
        } else {
            for (int64_t i = start; i > stop; i += step) {
                container[i] = values[value_idx++];
            }
        }
    }
}

// 切片删除：del list[start:stop:step]
template <typename Container>
void list_slice_delete(
    Container& container,
    int64_t    start = INT64_MIN,
    int64_t    stop  = INT64_MIN,
    int64_t    step  = 1) {
    int64_t size = static_cast<int64_t>(container.size());

    // 规范化索引
    normalize_slice_indices(size, &start, &stop, step);

    if (step == 1) {
        // step == 1: 删除连续区间
        if (start < stop) {
            container.erase(container.begin() + start, container.begin() + stop);
        }
    } else {
        // step != 1: 删除不连续的元素
        // 计算需要删除的元素个数
        int64_t delete_count = 0;
        if (step > 0) {
            delete_count = (start < stop) ? ((stop - start + step - 1) / step) : 0;
        } else {
            delete_count = (start > stop) ? ((start - stop - step - 1) / (-step)) : 0;
        }

        if (delete_count == 0) {
            return;
        }

        // 将保留的元素移动到正确位置
        int64_t write_pos = start;
        int64_t read_pos  = start;
        int64_t old_size  = static_cast<int64_t>(container.size());

        if (step > 0) {
            // 正向步长
            for (int64_t i = start; i < old_size; ++i) {
                // 检查当前位置是否在删除范围内
                bool should_delete = (i >= start && i < stop && (i - start) % step == 0);
                if (!should_delete) {
                    if (write_pos != read_pos) {
                        container[write_pos] = std::move(container[read_pos]);
                    }
                    ++write_pos;
                }
                ++read_pos;
            }
        } else {
            // 负向步长
            for (int64_t i = start; i < old_size; ++i) {
                // 检查当前位置是否在删除范围内
                bool should_delete = (i <= start && i > stop && (start - i) % (-step) == 0);
                if (!should_delete) {
                    if (write_pos != read_pos) {
                        container[write_pos] = std::move(container[read_pos]);
                    }
                    ++write_pos;
                }
                ++read_pos;
            }
        }

        // 调整容器大小
        container.resize(static_cast<size_t>(old_size - delete_count));
    }
}

// ============================================================================
// 外部模板声明：常用类型已在 list.cpp 中显式实例化
// 这避免了在每个使用处重复实例化，减少二进制代码膨胀
// ============================================================================

// mc::array<T> 的模板实例化
#define MC_LIST_TEMPLATE(prefix, T)                                                                       \
    prefix size_t list_index(const mc::array<T>&, const T&);                                              \
    prefix size_t list_index(const mc::array<T>&, const T&, int, int);                                    \
    prefix T      list_pop(mc::array<T>&, size_t);                                                        \
    prefix void   list_remove(mc::array<T>&, T&&);                                                        \
    prefix T      list_pop_back(mc::array<T>&);                                                           \
    prefix mc::array<T> list_concat(const mc::array<T>&, const mc::array<T>&);                            \
    prefix mc::variants list_concat(const mc::variants&, const mc::array<T>&);                            \
    prefix mc::array<T>& list_iadd(mc::array<T>&, const mc::array<T>&);                                   \
    prefix mc::variants& list_iadd(mc::variants&, const mc::array<T>&);                                   \
    prefix void          list_extend(mc::array<T>&, const mc::array<T>&);                                 \
    prefix bool          list_contains(const mc::array<T>&, const T&);                                    \
    prefix void          list_insert(mc::array<T>&, int, const T&);                                       \
    prefix size_t        list_count(const mc::array<T>&, const T&);                                       \
    prefix void          list_reverse(mc::array<T>&);                                                     \
    prefix T&            list_getitem(mc::array<T>&, int);                                                \
    prefix const T&      list_getitem(const mc::array<T>&, int);                                          \
    prefix void          list_setitem(mc::array<T>&, int, const T&);                                      \
    prefix void          list_delitem(mc::array<T>&, int);                                                \
    prefix mc::array<T> list_repeat(const mc::array<T>&, int);                                            \
    prefix mc::array<T>& list_imul(mc::array<T>&, int);                                                   \
    prefix std::string list_repr(const mc::array<T>&);                                                    \
    prefix void        list_sort(mc::array<T>&, bool);                                                    \
    prefix mc::array<T> list_slice(const mc::array<T>&, int64_t, int64_t, int64_t);                       \
    prefix void         list_slice_assign(mc::array<T>&, const mc::array<T>&, int64_t, int64_t, int64_t); \
    prefix void         list_slice_delete(mc::array<T>&, int64_t, int64_t, int64_t);

MC_LIST_TEMPLATE(extern template, int)
MC_LIST_TEMPLATE(extern template, double)
MC_LIST_TEMPLATE(extern template, std::string)

// mc::variants 的模板实例化（泛型容器操作）
#define MC_LIST_VARIANTS_TEMPLATE(prefix)                                           \
    prefix bool   list_contains(const mc::variants&, const mc::variant&);           \
    prefix void   list_insert(mc::variants&, int, const mc::variant&);              \
    prefix size_t list_count(const mc::variants&, const mc::variant&);              \
    prefix void   list_reverse(mc::variants&);                                      \
    prefix void   list_delitem(mc::variants&, int);                                 \
    prefix mc::variants list_repeat(const mc::variants&, int);                      \
    prefix mc::variants& list_imul(mc::variants&, int);                             \
    prefix std::string list_repr(const mc::variants&);                              \
    prefix void        list_sort(mc::variants&, bool);                              \
    prefix mc::variants list_slice(const mc::variants&, int64_t, int64_t, int64_t); \
    prefix void         list_slice_delete(mc::variants&, int64_t, int64_t, int64_t);

MC_LIST_VARIANTS_TEMPLATE(extern template)

} // namespace mcpy

#endif // MC_BUILTINS_LIST_H